#ifndef __BASE_XML_OBJECT_HPP__
#define __BASE_XML_OBJECT_HPP__

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <wx\wx.h>
#include <wx\propgrid\propgrid.h>

#include <SFML/System/Vector2.hpp>

#include <SmegTools/Pattern/Clonable.hpp>

namespace tinyxml2 {
    class XMLElement;
}

class SmegEditorCanvas;

////////////////////////////////////////////////////////////
/// Handler of an object in the scene
////////////////////////////////////////////////////////////
class BaseXMLObject : public smeg::tools::Clonable<BaseXMLObject>
{
public:    
    ////////////////////////////////////////////////////////////
    /// Default Constructor
    ///
    ////////////////////////////////////////////////////////////
                            BaseXMLObject();
    ////////////////////////////////////////////////////////////
    /// Copy Constructor
    ///
    /// \param _Copy :      Handler to copy from
    ///
    ////////////////////////////////////////////////////////////
                            BaseXMLObject( const BaseXMLObject& _Copy );
    ////////////////////////////////////////////////////////////
    /// Destructor
    ///
    ////////////////////////////////////////////////////////////
    virtual                 ~BaseXMLObject() {}

    ////////////////////////////////////////////////////////////
    /// Init the handler from properties
    /// BaseXMLObject::InitFromGrid need to be called AFTER the specialized class
    ///
    /// \param _pPropertyGrid :      Grid where infos are stored
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            InitFromGrid( wxPropertyGrid* _pPropertyGrid ) = 0;
    
    ////////////////////////////////////////////////////////////
    /// Init the handler from an XMLElement
    /// BaseXMLObject::InitFromXML need to be called AFTER the specialized class
    ///
    /// \param _pElement :           XML Element with info
    /// \param _ProjectPath :        Path to the project
    ///
    /// \return Whether the init was successful or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            InitFromXML( tinyxml2::XMLElement* _pElement, const wxString& _ProjectPath ) = 0;
    
    ////////////////////////////////////////////////////////////
    /// PostInit
    ///
    ////////////////////////////////////////////////////////////
    virtual void            PostInit() {}
    
    ////////////////////////////////////////////////////////////
    /// Return the value of a property
    ///
    /// \param _PropertyName :      Name of the property
    ///
    /// \return The value as a string
    ///
    ////////////////////////////////////////////////////////////
    virtual wxString        GetValueAsString( const wxString& _PropertyName ) const = 0;
    
    ////////////////////////////////////////////////////////////
    /// Return the value of a property with a choice
    ///
    /// \param _pChoiceProperty :    Property we want the choice
    ///
    /// \return The value of the choice
    ///
    ////////////////////////////////////////////////////////////
    virtual int             GetChoiceValue( wxPGProperty* _pChoiceProperty ) { return 0; }
    
    ////////////////////////////////////////////////////////////
    /// Handle the change of a property and apply it to the object
    ///
    /// \param _pPropertyGrid :      The property grid
    /// \param _pChangedProperty :   Property that has been changed
    ///
    /// \return Whether the object has been changed or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            OnPropertyChanged( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty ) = 0;
    
    ////////////////////////////////////////////////////////////
    /// Handle the double click on a property
    ///
    /// \param _pPropertyGrid :      The property grid
    /// \param _pChangedProperty :   Property that has been changed
    ///
    /// \return Whether the object has been changed or not
    ///
    ////////////////////////////////////////////////////////////
    virtual bool            OnPropertyDoubleClick( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty ) { return false; }
    
    ////////////////////////////////////////////////////////////
    /// Set the id of the object handler
    ///
    /// \param _IdStr : the id of the object handler
    ///
    ////////////////////////////////////////////////////////////
    void                    SetId( const wxString& _IdStr );
    
    ////////////////////////////////////////////////////////////
    /// Get the id of the object handler
    ///
    /// \return the id of the object handler
    ///
    ////////////////////////////////////////////////////////////
    const wxString&         GetId() const;
    
    ////////////////////////////////////////////////////////////
    /// Get the name of the object handler
    ///
    /// \return the name of the object handler
    ///
    ////////////////////////////////////////////////////////////
    virtual wxString        GetName() const = 0;
    
    ////////////////////////////////////////////////////////////
    /// Create an XML string that define the object
    ///
    /// \param _ProjectPath :   Path to the project
    /// \param _Tab :           Tab string to have a beautiful XML
    ///
    /// \return the XML String
    ///
    ////////////////////////////////////////////////////////////
    wxString                ToXMLString( const wxString& _ProjectPath = wxEmptyString, const wxString& _Tab = wxT( "\t" ) ) const;

protected:
    wxString                m_ID;
    int                     m_iIconId;
    
    ////////////////////////////////////////////////////////////
    /// Create an XML string with the value of the object
    ///
    /// \param _ProjectPath :   Path to the project
    /// \param _Tab :           Tab string to have a beautiful XML
    ///
    /// \return the XML String
    ///
    ////////////////////////////////////////////////////////////
    virtual wxString        InnerXMLString( const wxString& _ProjectPath = wxEmptyString, const wxString& _Tab = wxT( "\t" ) ) const = 0;
};
    
////////////////////////////////////////////////////////////
/// Set the id of the object handler
////////////////////////////////////////////////////////////
inline void BaseXMLObject::SetId( const wxString& _IdStr ) {
    m_ID = _IdStr;
}

////////////////////////////////////////////////////////////
/// Get the id of the object handler
////////////////////////////////////////////////////////////
inline const wxString& BaseXMLObject::GetId() const {
    return m_ID;
}

#endif // __BASE_XML_OBJECT_HPP__